﻿using System;
using System.Linq;
using ESoft.Core.Util.Extensions;
using ESoft.Core.Web.Config;
using ESoft.Core.Web.VO;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Configuration;

namespace ESoft.Core.Web.Common.Filters
{
    /// <summary>
    /// 前台登录验证
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class UserAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter
    {
        private readonly IConfiguration _configuration;

        public UserAuthorizeAttribute(IConfiguration configuration)
        {
            _configuration = configuration;
        }
        public virtual void OnAuthorization(AuthorizationFilterContext filterContext)
        {
            string userAuth = _configuration[WebParameter.UserAuthenticationScheme] ?? "DefaultAuth";
            var authenticate = filterContext.HttpContext.AuthenticateAsync(userAuth);
            if (authenticate.Result.Succeeded || this.SkipUserAuthorize(filterContext.ActionDescriptor))
            {
                return;
            }

            var httpRequest = filterContext.HttpContext.Request;

            if (httpRequest.IsAjax())
            {
                filterContext.Result = new JsonResult(ResponseResult.FailOut(ResponseResult.LOGIN_TIME_OUT, new Exception("登陆信息已过期，请重新登录！")));
            }
            else
            {
                string url = string.Concat(_configuration[WebParameter.UserSignInUrl], "?returnUrl=", httpRequest.Path);
                RedirectResult redirectResult = new RedirectResult(url);
                filterContext.Result = redirectResult;
            }
        }

        protected virtual bool SkipUserAuthorize(ActionDescriptor actionDescriptor)
        {
            bool skipAuthorize = actionDescriptor.FilterDescriptors.Any(a =>
                a.Filter is IAllowAnonymous);
            return skipAuthorize;
        }
    }
}
